package com.xuxueli.applyModules.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.xuxueli.applyModules.entity.User;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 测试stream流
 */
public class TestStream {

    private static Gson gson = new GsonBuilder().serializeNulls().setDateFormat("yyyyMMddHHmmss").create();
    private static Type type = new TypeToken<List<User>>() {}.getType();

    public static void main(String[] args) {
        String value = "[{\"copGNo\":\"m3\",\"cosTs\":\"1\",\"curr\":\"\",\"entryNo\":\"\",\"gName\":\"\",\"isExist\":true,\"peoplePara\":null,\"primaryNote\":\"\",\"serialNo\":1,\"sid\":\"3\",\"tempFlag\":true,\"tempRemark\":\"\",\"timeStamp\":0,\"unit\":\"\",\"validDatetime\":\"\",\"valueStr\":\"\"},{\"copGNo\":\"m4\",\"cosTs\":\"2\",\"curr\":\"\",\"entryNo\":\"\",\"gName\":\"\",\"isExist\":true,\"peoplePara\":null,\"primaryNote\":\"\",\"serialNo\":6,\"sid\":\"4\",\"tempFlag\":true,\"tempRemark\":\"\",\"timeStamp\":0,\"unit\":\"\",\"validDatetime\":\"\",\"valueStr\":\"\"}]";
        value.replace("\"{","{").replace("}\"","}").replace("\\\\","");
        List<User> testModals = (List<User>) gson.fromJson(value, type);
        System.out.println(testModals);
        List<User> list = new ArrayList<>();
        User user = new User();
        user.setName("2021");
        User users = new User();
        users.setName("2020");
        list.add(user);
        list.add(users);
        list.stream().sorted(Comparator.comparing(User::getName, Comparator.nullsLast(String::compareTo)).reversed()).collect(Collectors.toList());
        System.out.println(list);
        int pageSize = 2;
        int pageIndex = 3;//必须大于等于1
        if(pageIndex<=1){
            pageIndex = 1;
        }
        //第一个方法分页
        List<User> areaVo = list.stream()
                .skip(pageSize * (pageIndex - 1))
                .limit(pageSize).collect(Collectors.toList());
        System.out.println("stream，skip，limit第一个方法分页值："+areaVo);
        ResultObject resultObject = ResultObject.createInstance(true);
        resultObject.setPageIndex(pageIndex);
        resultObject.setData(areaVo);
        resultObject.setTotal(list.size());
        System.out.println("resultObject分页值："+resultObject);
        Integer maxPageCount = 0;
        if (list.size() %pageSize == 0) {
            maxPageCount = list.size() / pageSize;
        } else {
            //如果一页放不下，则直接+1
            maxPageCount = (list.size() / pageSize)+1;
        }
        if(maxPageCount<pageIndex){
            pageIndex = maxPageCount;
        }
        //第二个方法分页
        List<User> testModalList1 = list.subList(pageSize * (pageIndex - 1), pageSize);
        System.out.println("subList分页1值："+testModalList1);
        List<User> userList = Collections.synchronizedList(testModalList1);
        System.out.println("同步list集合："+userList);
        Set<String> setList = new HashSet<>();
        setList.add("tesry");
        Set<String> sList = Collections.synchronizedSet(setList);
        System.out.println("同步set集合："+sList);
        Map<String, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("code", RandomStringUtils.random(18,true,true));
        Map<String, Object> stringObjectMap = Collections.synchronizedMap(objectObjectHashMap);
        System.out.println("同步map集合："+stringObjectMap);
        List emptyList = Collections.EMPTY_LIST;
        emptyList.add(objectObjectHashMap);//报错
        testStream();
        testOther();
    }

    /**
     * 各个方法实例
     */
    private static void testStream(){
        List<User> list = new ArrayList<>();
        User user = new User();
        user.setName("2021");
        //user.setDept("测试");
        user.setAmount(new BigDecimal("468"));
        User users = new User();
        users.setName("2020");
        //users.setDept("test");
        users.setAmount(new BigDecimal("468"));
        list.add(user);
        list.add(users);
        //循环处理数字多余0，科学计数法
        list.parallelStream().forEach(item->
                item.setAmountStr((item.getAmount()==null?"0":item.getAmount().stripTrailingZeros().toPlainString()))
        );
        System.out.println(list);
        //根据金额排序
        List<User> sortLists = list.stream().sorted(Comparator.comparing(User::getAmount)).collect(Collectors.toList());
        System.out.println(sortLists);
        //初始化集合，泛型为string
        List<String> stringList2 = Arrays.asList("a", "b");
        //任意一个匹配上就返回true
        boolean ron1 = list.stream().anyMatch(u -> u.getName().equals("Ron"));
        System.out.println(ron1);
        //所有匹配上就返回true
        boolean ron2 = list.stream().allMatch(u -> u.getName().equals("Ron"));
        System.out.println(ron2);
        //所有不匹配上就返回true
        boolean ron3 = list.stream(). noneMatch(u -> u.getName().equals("Ron"));
        System.out.println(ron3);
        //过滤值不为空却包含对应的集合
        List<User> statusLists = list.parallelStream().filter(item -> (StringUtils.isNotBlank(item.getName()) && stringList2.contains(item.getName()))).collect(Collectors.toList());
        System.out.println(statusLists);
        //过滤值不为空
        List<User> statusList = list.parallelStream().filter(item -> StringUtils.isNotBlank(item.getName())).collect(Collectors.toList());
        //统计集合某一个值为test个数
        long count = statusList.parallelStream().filter(item -> item.getName().equals("test")).count();
        System.out.println(count);
        //从集合提出某一个值得集合
        List<String> stringList = statusList.parallelStream().map(item -> item.getName()).collect(Collectors.toList());
        //集合转string,以-分割
        String string2 = stringList.stream().collect(Collectors.joining("-"));
        List<String> stringList1 = Arrays.asList(string2);
        System.out.println(stringList1);
        //list转set集合
        Set<User> statusSet = list.parallelStream().filter(item -> StringUtils.isNotBlank(item.getName())).collect(Collectors.toSet());
        System.out.println(statusSet);
        //list转map,value为对象
        Map<String,User> statusMap1 = list.stream().collect(Collectors.toMap(User::getName, Function.identity(),(key1, key2)->key2));
        //Map<String, String> statusMap2 = dcEntryPushStatuseList.parallelStream().collect(Collectors.toMap(DcEntryPushStatus::getBillListNo, DcEntryPushStatus::getEmsNo));
        System.out.println(statusMap1);
        //System.out.println(statusMap2);
        //list转map,value为string
        Map<String, String> map = list.parallelStream().collect(Collectors.toMap(v-> Optional.ofNullable(v.getName()).orElse(""), v-> Optional.ofNullable(v.getDept()).orElse(""),(oldValue,newValue)->newValue));
        //map更新值并且处理value为null报空指针
        Map<String, String> maps = map.entrySet().stream().filter(e-> e.getKey() != null && e.getKey().startsWith("SOCIAL_CREDIT_CODE_"))
                .collect(Collectors.toMap((item -> item.getKey().replace("SOCIAL_CREDIT_CODE_", "")),(items-> Optional.ofNullable(items.getValue()).orElse(""))));
        System.out.println(maps);
        //根据BillListNo分组并轮询操作
        Map<String, List<User>> dcEntryPushStatusMap = list.stream().collect(Collectors.groupingBy(User::getName));
        //循环map,取key,value为集合
        for (Map.Entry<String, List<User>> dcEntryPushStatusMapEntry : dcEntryPushStatusMap.entrySet()) {
            String billListNo = dcEntryPushStatusMapEntry.getKey();
            System.out.println(billListNo);
            List<User> dcEntryPushStatusList = dcEntryPushStatusMapEntry.getValue();
            List<User> sortList = dcEntryPushStatusList.stream().sorted(Comparator.comparing(User::getName)).collect(Collectors.toList());
            System.out.println(sortList);
        }
        list.stream().sorted(Comparator.comparing(User::getName, Comparator.nullsLast(String::compareTo)).reversed()).collect(Collectors.toList());
        System.out.println(list);
        // 用于收集统计数据的状态对象，例如count，min，max，sum和平均。
        IntSummaryStatistics stats = list.stream().mapToInt((user1) -> user1.getCountSum()).summaryStatistics();
        System.out.println("最大Max : " + stats.getMax());
        System.out.println("最小Min: " + stats.getMin());
        System.out.println("求和Sun: " + stats.getSum());
        System.out.println("平均数Average : " + stats.getAverage());
        System.out.println("个数Count : " + stats.getCount());
        System.out.println("转字符串toString : " + stats.toString());
        int intObjectListSize = list.size();
        Set<String> sets = new HashSet<>(intObjectListSize);
        Map<String, List<User>> listMap = list.stream().map(item -> {
            item.setDescriptions(item.getName() + item.getDept());
            if(sets.contains(item.getDescriptions())){
                item.setDescription("导入文件中成品料号+料件料号+单耗版本号不能重复!");
            }
            sets.add(item.getDescriptions());
            return item;
        }).collect(Collectors.groupingBy(User::getDescriptions));
        System.out.println("list转map分组："+listMap);
        list.parallelStream().filter(ss->{
            if(listMap.containsKey(ss.getDescriptions())){
                if(listMap.get(ss.getDescriptions()).size()>1){
                    ss.setDescription("导入文件中成品料号+料件料号+单耗版本号不能重复!");
                }
                return true;
            }else{
                return false;
            }
        }).collect(Collectors.toList());
        System.out.println("list校验集合："+list);
        List<User> listBySids = list;
        List<User> collectNot = listBySids.parallelStream().filter(item -> StringUtils.isNotEmpty(item.getDescriptions())).collect(Collectors.toList());
        List<User> collect = listBySids.parallelStream().filter(item -> StringUtils.isEmpty(item.getDescriptions())).collect(Collectors.toList());
        List<String> dctimesStr = collectNot.parallelStream().map(item->item.getDescription()!=null?item.getDescription().toString():"").collect(Collectors.toList());
        List<String> sidStrs = collect.parallelStream().map(User::getId).collect(Collectors.toList());
        String mergeString = dctimesStr.parallelStream().filter(string -> !string.isEmpty()).collect(Collectors.joining("、"));
        User user1 = new User();
        List<String> sids = new ArrayList<>();
        if(StringUtils.isNotEmpty(mergeString)) {
            user1.setDescription("报核次数" + mergeString + "已开始报核无需启用提醒");
            sids = sidStrs;
            if (sidStrs.size() > 0) {
                System.out.println("启动集合1："+ JSON.toJSONString(sids, SerializerFeature.WriteNullStringAsEmpty));
            }else{
                System.out.println("启动集合2："+ JSON.toJSONString(sids, SerializerFeature.WriteNullStringAsEmpty));
            }
        }
    }

    /**
     * 测试其他
     */
    private static void testOther(){
        String validDatetime = "1212012121-21";
        if(StringUtils.isBlank(validDatetime)){
            validDatetime = "2050-12-31";
        }else {
            String eL= "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
            Pattern p = Pattern.compile(eL);
            Matcher m = p.matcher(validDatetime);
            boolean b = m.matches();
            if(!b) {
                System.out.println("|单损耗有效期格式不正确");
            }
        }
        SimpleDateFormat format = new SimpleDateFormat("今天是 " + "yyyy 年 MM 月 dd 日 E HH 点 mm 分 ss 秒");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.HOUR,1);
        Date deleteDate = calendar.getTime();
        System.out.println(format.format(deleteDate));
        String[] arr = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18".split(",");
        List<String> stringList = Arrays.asList(arr);
        List<Long> timeStamps = Collections.EMPTY_LIST;
        List<User> list = new ArrayList<>();
        User user = new User();
        user.setName("2021");
        user.setTimeStamp(1243241212L);
        User users = new User();
        users.setName("2020");
        users.setTimeStamp(12432212L);
        list.add(user);
        list.add(users);
        List<Long> longList = list.stream().map(User::getTimeStamp).collect(Collectors.toList());
        timeStamps = list.stream().map(v-> Optional.ofNullable(v.getTimeStamp()).orElse(0L)).collect(Collectors.toList());
        long timeStamp = 0L;
        try{
            if(CollectionUtils.isEmpty(timeStamps)){
                System.out.println("Collections.max里的list不能为空");
            }else{
                timeStamp = Collections.max(timeStamps);
            }
            System.out.println("最大时间戳："+timeStamp);
        }catch (Exception ex){
            String message = ex.getMessage();
            if(StringUtils.isBlank(message)){
                message = ex.toString();
            }
            System.out.println("Collections.max错误信息："+message);
        }
        List<BigDecimal> entryGNos = list.stream().map(el -> el.getEntryGNo()).distinct().collect(Collectors.toList());
        Collections.sort(entryGNos);
        for (int i = 0; i < entryGNos.size() - 1; i++) {
            int nextEntryGNo = entryGNos.get(i + 1).intValue();
            int currentEntryGNo = entryGNos.get(i).intValue();
            int diff = nextEntryGNo - currentEntryGNo;
            if (diff != 1) {
                list.stream().filter(e -> nextEntryGNo <= e.getEntryGNo().intValue()).collect(Collectors.toList()).forEach(el -> {
                    el.setTempFlag(false);
                    el.setTempRemark(String.format("归并序号不连续，可能为序号为%d的数据错误或不存在，请检查！", nextEntryGNo - 1));
                });
            }
        }
        Integer BATCHE_SIZE = 1000;
        for (int i = 0; i <= stringList.size()/BATCHE_SIZE; i++) {
            Integer fromSize = BATCHE_SIZE*i;
            Integer toSize = BATCHE_SIZE*(i+1);
            if(toSize > stringList.size()){
                toSize = stringList.size();
            }
            List<String> stringList1 = stringList.subList(fromSize, toSize);
            System.out.println(stringList1.toString());
        }
        for (int i = 0; i < stringList.size()/6f; i++) {
            Integer fromSize = 6*i;
            Integer toSize = 6*(i+1);
            if(toSize > stringList.size()){
                toSize = stringList.size();
            }
            List<String> stringList1 = stringList.subList(fromSize, toSize);
            System.out.println(stringList1.toString());
        }
        Set<String> codeSet = new HashSet<>();
        codeSet.add("6688");
        codeSet.add("9988");
        List<Map<String, String>> companyList = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("CODE","6688");
        map.put("NAME","");
        map.put("SOCIAL_CREDIT_CODE","88798");
        companyList.add(map);
        Map<String, String> companyInfos = getCompanyInfos(codeSet, "com", companyList);
        Map<String, String> creditCodeMap = getCreditCodeMap(companyInfos);
        System.out.println(companyInfos.toString());
        System.out.println(creditCodeMap.toString());
        List<String> listsss = new ArrayList<>();
        for (User dcBillList:list) {
            //判断序号是否已经存在
            long cnt = list.stream().filter(i -> {
                return (i.getName()+i.getEntryGNo()).equals(dcBillList.getName()+dcBillList.getEntryGNo());
            }).count();
            if (cnt > 1) {
                dcBillList.setTempRemark(dcBillList.getTempRemark()+"|成品料号+版本号已经存在！");
            }
        }
    }

    /**
     * 根据Code批量查询PCode
     * @param codeSet
     * @return Map
     */
    public static Map<String, String> getCompanyInfos(Set<String> codeSet, String type,List<Map<String, String>> companyList) {
        if(codeSet.size()>0) {
            Set<String> filteredSet = codeSet.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet());
            if(filteredSet.isEmpty()) {
                return Collections.emptyMap();
            }
            if(companyList.size()>0) {
                Map<String, String> map = new HashMap<>();
                for(Map<String, String> company : companyList) {
                    map.put(company.get("CODE"), company.get("NAME"));
                    map.put("SOCIAL_CREDIT_CODE_" + company.get("CODE"), company.get("SOCIAL_CREDIT_CODE"));
                }
                return map;
            }
        }
        return Collections.emptyMap();
    }

    public static Map<String, String> getCreditCodeMap(Map<String, String> map) {
        if(map == null || map.isEmpty()) {
            return Collections.emptyMap();
        } else {
            return map.entrySet().stream().filter(e-> e.getKey() != null && e.getKey().startsWith("SOCIAL_CREDIT_CODE_"))
                    .collect(Collectors.toMap((e -> e.getKey().replace("SOCIAL_CREDIT_CODE_", "")),
                            v-> Optional.ofNullable(v.getValue()).orElse("")));
        }
    }

}
